
#ifndef __RT_MEMORYPOOL_T_H__
#define __RT_MEMORYPOOL_T_H__

/// Use queue or list as the container. 
#ifdef POOL_USE_QUEUE
	#include "RtQueueT.h"
#else
	#include "RtListT.h"
#endif // POOL_USE_QUEUE

#define CHECK_MEMORY_POOL

template<typename DataType>
class CRtMemoryPoolT
{
public:
	CRtMemoryPoolT(const CRtString& inDescription = "")
		: m_description(inDescription)
#ifdef CHECK_MEMORY_POOL
		, m_blocksOut(0)
#endif
	{	
	}
	
	~CRtMemoryPoolT()
	{
#ifdef CHECK_MEMORY_POOL
		RT_INFO_TRACE_THIS("~CRtMemoryPoolT, size="<<m_pool.Size()<<" desc="<<m_description/*<<" sizeof(DataType)="<<sizeof(DataType)*/
			<<" leak="<<m_blocksOut);
#else
		RT_INFO_TRACE_THIS("~CRtMemoryPoolT, size="<<m_pool.Size()<<" desc="<<m_description/*<<" sizeof(DataType)="<<sizeof(DataType)*/);
#endif
		ClearPool();
	}

	void Preallocate(unsigned inSize)
	{
#ifdef POOL_USE_QUEUE
		m_pool.ClearAndForceAllocation(inSize);
#else
		m_pool.Preallocate(inSize);
#endif // POOL_USE_QUEUE

		for (unsigned i=0; i < inSize; ++i)
			m_pool.Push(new DataType);
	}

	DataType* New()
	{
#ifdef CHECK_MEMORY_POOL
		++m_blocksOut;
#endif
		return m_pool.IsEmpty() ? (new DataType) : m_pool.Pop();
	}
	
	void Delete(DataType* p)
	{
		if ( p == 0 )
			return ;

#ifdef CHECK_MEMORY_POOL
		RT_ASSERTE(m_blocksOut>0);
		--m_blocksOut;
#endif

		p->Release();
		m_pool.Push(p);
	}

	void ClearPool( unsigned reservedSize = 0 )
	{
		while ( m_pool.Size() > reservedSize )
			delete m_pool.Pop();
	}

private:

#ifdef POOL_USE_QUEUE
	typedef DataStructures::Queue<DataType*> RtPoolType;
#else
	typedef DataStructures::List<DataType*> RtPoolType;
#endif // POOL_USE_QUEUE

	RtPoolType m_pool;
	CRtString m_description;
#ifdef CHECK_MEMORY_POOL
	int m_blocksOut;
#endif
};

/*
//////////////////////////////////////////////////////////////////////////

#ifdef CHECK_MEMORY_POOL
#define RT_ASSERTE_AND_DECREASE_BLOCKSOUT \
	RT_ASSERTE(m_blocksOut>0); \
	--m_blocksOut
#else
#define RT_ASSERTE_AND_DECREASE_BLOCKSOUT 
#endif

#define RT_SPECIALIZE_MEMORYPOOL_DELETE(Type) \
template<> void CRtMemoryPoolT<Type>::Delete(Type* p) \
{ \
	if ( p == 0 ) \
		return ; \
	RT_ASSERTE_AND_DECREASE_BLOCKSOUT; \
	m_pool.Push(p); \
}

//////////////////////////////////////////////////////////////////////////

RT_SPECIALIZE_MEMORYPOOL_DELETE(char)
RT_SPECIALIZE_MEMORYPOOL_DELETE(unsigned char)
RT_SPECIALIZE_MEMORYPOOL_DELETE(short)
RT_SPECIALIZE_MEMORYPOOL_DELETE(unsigned short)
RT_SPECIALIZE_MEMORYPOOL_DELETE(int)
RT_SPECIALIZE_MEMORYPOOL_DELETE(unsigned int)
RT_SPECIALIZE_MEMORYPOOL_DELETE(long)
RT_SPECIALIZE_MEMORYPOOL_DELETE(unsigned long)
RT_SPECIALIZE_MEMORYPOOL_DELETE(LONGLONG)

RT_SPECIALIZE_MEMORYPOOL_DELETE(float)
RT_SPECIALIZE_MEMORYPOOL_DELETE(double)

RT_SPECIALIZE_MEMORYPOOL_DELETE(bool)
RT_SPECIALIZE_MEMORYPOOL_DELETE(void*)
*/

#endif // __RT_MEMORYPOOL_T_H__

